{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "github地址:[https://github.com/cheesezh/python_design_patterns](https://github.com/cheesezh/python_design_patterns)\n",
    "   \n",
    "## 迭代器模式\n",
    "\n",
    "迭代器模式，提供一种方法顺序访问一个聚合对象中各个元素，而又不暴露该对象的内部表示[DP]。\n",
    "\n",
    "当需要访问一个聚集对象，而且不管这些对象是什么都需要遍历的时候，就应该考虑使用迭代器模式。\n",
    "\n",
    "当需要对聚集有多种方式遍历时，也可以考虑使用迭代器模式。\n",
    "\n",
    "迭代器为遍历不同的聚集结构提供如开始，下一个，是否结束，当前哪一项等统一接口。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "aa 买车票\n",
      "bb 买车票\n",
      "cc 买车票\n",
      "dd 买车票\n",
      "ee 买车票\n"
     ]
    }
   ],
   "source": [
    "from abc import ABCMeta, abstractmethod\n",
    "\n",
    "\n",
    "class Iterator():\n",
    "    \"\"\"\n",
    "    迭代器抽象类，定义得到开始对象，得到下一对象，判断是否结尾，得到当前对象等方法\n",
    "    \"\"\"\n",
    "    __metaclass__ = ABCMeta\n",
    "    \n",
    "    @abstractmethod\n",
    "    def first(self):\n",
    "        pass\n",
    "    \n",
    "    @abstractmethod\n",
    "    def next(self):\n",
    "        pass\n",
    "    \n",
    "    @abstractmethod\n",
    "    def is_done(self):\n",
    "        pass\n",
    "    \n",
    "    @abstractmethod\n",
    "    def current_item(self):\n",
    "        pass\n",
    "    \n",
    "    \n",
    "class Aggregate():\n",
    "    \"\"\"\n",
    "    聚集抽象类\n",
    "    \"\"\"\n",
    "    __metaclass__ = ABCMeta\n",
    "    \n",
    "    @abstractmethod\n",
    "    def create_iterator(self):\n",
    "        pass\n",
    "    \n",
    "    \n",
    "class ConcreteIterator(Iterator):\n",
    "    \"\"\"\n",
    "    具体迭代器类\n",
    "    \"\"\"\n",
    "    def __init__(self, aggregate):\n",
    "        # 定义一个具体的聚集对象，初始化时将具体的聚集对象传入\n",
    "        self.aggregate = aggregate\n",
    "        self.current = 0\n",
    "        \n",
    "    def first(self):\n",
    "        # 得到聚集的第一个对象\n",
    "        return self.aggregate.get_value(0)\n",
    "    \n",
    "    def next(self):\n",
    "        # 得到聚集的下一个对象\n",
    "        ret = None\n",
    "        self.current += 1\n",
    "        if self.current < self.aggregate.length:\n",
    "            ret = self.aggregate.get_value(self.current)\n",
    "        return ret\n",
    "    \n",
    "    def is_done(self):\n",
    "        return True if self.current >= self.aggregate.length else False\n",
    "    \n",
    "    def current_item(self):\n",
    "        return self.aggregate.get_value(self.current)\n",
    "    \n",
    "    \n",
    "class ConcreteAggregate(Aggregate):\n",
    "    \"\"\"\n",
    "    具体聚集类\n",
    "    \"\"\"\n",
    "    def __init__(self):\n",
    "        self.list = []\n",
    "        self.length = 0\n",
    "    \n",
    "    def create_iterator(self):\n",
    "        return ConcreteIterator(self)\n",
    "    \n",
    "    def create_iterator_desc(self):\n",
    "        return ConcreteIteratorDesc(self)\n",
    "    \n",
    "    def insert_value(self, value):\n",
    "        self.list.append(value)\n",
    "        self.length += 1\n",
    "        \n",
    "    def get_value(self, index):\n",
    "        return self.list[index]\n",
    "\n",
    "    \n",
    "def main():\n",
    "    agg = ConcreteAggregate()\n",
    "    agg.insert_value(\"aa\")\n",
    "    agg.insert_value(\"bb\")\n",
    "    agg.insert_value(\"cc\")\n",
    "    agg.insert_value(\"dd\")\n",
    "    agg.insert_value(\"ee\")\n",
    "    \n",
    "    i = agg.create_iterator()\n",
    "    \n",
    "    item = i.first()\n",
    "    while i.is_done() == False:\n",
    "        print(\"{} 买车票\".format(i.current_item()))\n",
    "        i.next()\n",
    "        \n",
    "main()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 逆序遍历"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "ee 买车票\n",
      "dd 买车票\n",
      "cc 买车票\n",
      "bb 买车票\n",
      "aa 买车票\n"
     ]
    }
   ],
   "source": [
    "class ConcreteIteratorDesc(Iterator):\n",
    "    \"\"\"\n",
    "    具体迭代器类，逆序遍历\n",
    "    \"\"\"\n",
    "    def __init__(self, aggregate):\n",
    "        # 定义一个具体的聚集对象，初始化时将具体的聚集对象传入\n",
    "        self.aggregate = aggregate\n",
    "        self.current = self.aggregate.length-1\n",
    "        \n",
    "    def first(self):\n",
    "        # 得到聚集的第一个对象\n",
    "        return self.aggregate.get_value(self.aggregate.length-1)\n",
    "    \n",
    "    def next(self):\n",
    "        # 得到聚集的下一个对象\n",
    "        ret = None\n",
    "        self.current -= 1\n",
    "        if self.current >= 0:\n",
    "            ret = self.aggregate.get_value(self.current)\n",
    "        return ret\n",
    "    \n",
    "    def is_done(self):\n",
    "        return True if self.current < 0 else False\n",
    "    \n",
    "    def current_item(self):\n",
    "        return self.aggregate.get_value(self.current)\n",
    "    \n",
    "    \n",
    "def main():\n",
    "    agg = ConcreteAggregate()\n",
    "    agg.insert_value(\"aa\")\n",
    "    agg.insert_value(\"bb\")\n",
    "    agg.insert_value(\"cc\")\n",
    "    agg.insert_value(\"dd\")\n",
    "    agg.insert_value(\"ee\")\n",
    "    \n",
    "    i = agg.create_iterator_desc()\n",
    "    \n",
    "    item = i.first()\n",
    "    while i.is_done() == False:\n",
    "        print(\"{} 买车票\".format(i.current_item()))\n",
    "        i.next()\n",
    "        \n",
    "main()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 点评\n",
    "总的来说，迭代器模式就是分离了集合对象的遍历行为，抽象出一个迭代器类来负责，这样既可以做到不暴露集合的内部结构，又可以让外部代码透明的访问集合内部的数据。"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.4"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
